package com.fowo.api.service.purchase;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fowo.api.common.model.R;
import com.fowo.api.entity.*;
import com.fowo.api.flow.entity.ProcessTemplates;
import com.fowo.api.flow.model.dto.StartProcessInstanceDTO;
import com.fowo.api.flow.model.vo.TemplateVo;
import com.fowo.api.flow.service.FlowService;
import com.fowo.api.flow.service.ProcessTemplateService;
import com.fowo.api.model.purchase.change.order.PurchaseChangeOrderVo;
import com.fowo.api.model.purchase.change.order.product.PurchaseChangeOrderProductItemVo;
import com.fowo.api.service.PurchaseChangeOrderService;
import com.fowo.api.service.impl.*;
import com.fowo.api.user.model.CurrentUser;
import com.fowo.api.user.model.JwtUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class PurchaseChangeOrderDServiceImpl implements PurchaseChangeOrderDService{

    @Resource
    private PurchaseChangeOrderServiceImpl purchaseChangeOrderService;
    @Resource
    private PurchaseOrderServiceImpl purchaseOrderService;
    @Resource
    protected PurchaseOrderProductServiceImpl purchaseOrderProductService;
    @Resource
    protected StockInProductServiceImpl stockInProductService;
    @Resource
    protected FundsPayOrderServiceImpl fundsPayOrderService;
    @Resource
    private ListingFatherServiceImpl listingFatherService;
    @Resource
    private ProcessTemplateService processTemplateService;
    @Resource
    private FlowService flowService;
    @Resource
    private PurchaseChangeOrderServiceImpl PurchaseChangeOrderService;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized Long create(PurchaseChangeOrderVo model) throws Exception {
        PurchaseChangeOrder purchaseChangeOrder = purchaseChangeOrderService.getOne(Wrappers.lambdaQuery(PurchaseChangeOrder.class)
                .eq(PurchaseChangeOrder::getOrderSn, model.getOrderSn())
                .eq(PurchaseChangeOrder::getStatus, "0"));
        Assert.isNull(purchaseChangeOrder,"该订单存在待审批变更单");
        model.setStatus("0");
        //检查是否有到货数量大于采购数量的
        checkData(model);
        //检查变更后的金额不得小于已付款的金额
        checkFundsPayOrder(model);
        //设置参数
        enteringGinseng(model);
        model.getProductItem().forEach(x->{
            if( x.getFnsku()!=null){
                ListingFather byId = listingFatherService.getById(x.getFnsku());
                x.setFnskuFnsku(byId.getFnsku());
            }
        });
        Long aLong = purchaseChangeOrderService.create(model);
        //发起提交流程
        queryByTableName("PurchaseChangeOrder", String.valueOf(aLong));
        return aLong;
    }

    public void queryByTableName(String tableName,String recordId) throws Exception {
        List<TemplateVo> templateVos = processTemplateService.queryByTableName(tableName);
        Assert.isTrue(templateVos.size()>0,"没有配置审批流程");
        JwtUserInfo jwtUserInfo = JwtUserInfo.fromHeader();
        TemplateVo templateVo = templateVos.get(0);

        //查询模板详情
        ProcessTemplates detail = flowService.detail(templateVo.getTemplateId());
        List<StartProcessInstanceDTO> startList=new ArrayList<>();
        StartProcessInstanceDTO StartProcessInstanceDTO=new StartProcessInstanceDTO();
        PurchaseChangeOrder byId = PurchaseChangeOrderService.getById(recordId);
        StartProcessInstanceDTO.setFormData((JSONObject) JSONObject.toJSON(byId));
        StartProcessInstanceDTO.setTemplateId(templateVo.getTemplateId());
        StartProcessInstanceDTO.setProcessDefinitionId(detail.getProcessDefinitionId());
        StartProcessInstanceDTO.setRecordId(Long.valueOf(recordId));
        StartProcessInstanceDTO.setFormName(tableName);

        CurrentUser currentUser=new CurrentUser();
        currentUser.setUserid(String.valueOf(jwtUserInfo.getUserId()));
        StartProcessInstanceDTO.setStartUserInfo(currentUser);
        startList.add(StartProcessInstanceDTO);
        R<Object> start = flowService.start(startList);
       Assert.isTrue(start.isSuccess(),start.getErrorMessage());
    }
    /**
     * 设置参数
     * @param model
     */
    private void enteringGinseng(PurchaseChangeOrderVo model) {
        final List<PurchaseChangeOrderProductItemVo> productItem = model.getProductItem();
        PurchaseOrder purchaseOrder = purchaseOrderService.getOne(Wrappers.<PurchaseOrder>query().lambda().eq(PurchaseOrder::getPurchaseOrderCode, model.getOrderSn()));
        //设置主标参数、判断是否有子表入库了
        List<PurchaseOrderProduct> list = purchaseOrderProductService.list(Wrappers.<PurchaseOrderProduct>query().lambda()
                .eq(PurchaseOrderProduct::getPurchaseOrderId, purchaseOrder.getId()));
        int sum = 0;
        int purchaseQuantity = 0;
        for(PurchaseOrderProduct purchaseOrderProduct : list){
            Integer quantityReceived = purchaseOrderProduct.getQuantityReceived();
            if(quantityReceived != null && quantityReceived > 0){ //已经到货不支持移除,新数量不得低于到货量。
                final PurchaseChangeOrderProductItemVo purchaseChangeOrderProductItemVo = productItem.stream().filter(item -> item.getPurchaseOrderProductId().equals(purchaseOrderProduct.getId())).findFirst().get();
                Assert.isTrue(purchaseChangeOrderProductItemVo != null
                        ,purchaseOrderProduct.getProductName()+"已到过货，不支持移除");
                Assert.isTrue(purchaseChangeOrderProductItemVo.getApplicationNum() >= quantityReceived,purchaseOrderProduct.getProductName()+"已到过货，新数量不得低于到货量");
                sum += quantityReceived;
                purchaseQuantity += purchaseOrderProduct.getApplicationNum();
            }
        }
//        double sum = list.stream().mapToDouble(PurchaseOrderProduct::getQuantityReceived).sum();
        model.setPurchaseType("0");
        model.setOldquantity(purchaseQuantity);
        model.setOldAmount(purchaseOrder.getTotalPrice() == null ? new BigDecimal(0.0) : new BigDecimal(purchaseOrder.getTotalPrice()));
        if(sum==0){
            model.setSupplierId(model.getSupplierId());
            model.setWid(model.getWid());
            model.setOptUid(model.getOptUid());
            model.setFeePartType(model.getFeePartType());
            model.setInspectionType(model.getInspectionType());
        }
    }

    /**
     * 检查是否有到货数量大于采购数量的
     * @param model
     */
    private void checkData(PurchaseChangeOrderVo model) {
        List<PurchaseChangeOrderProductItemVo> productItem=model.getProductItem();
        for(int i=0;i<productItem.size();i++){
            PurchaseChangeOrderProductItemVo purchaseChangeOrderProductItemVo = productItem.get(i);
            if(purchaseChangeOrderProductItemVo.getPurchaseOrderProductId()!=null){
                PurchaseOrderProduct byId = purchaseOrderProductService.getById(purchaseChangeOrderProductItemVo.getPurchaseOrderProductId());
                if(byId.getQuantityReceived()!=null){
                    Assert.isTrue(byId.getQuantityReceived()<=purchaseChangeOrderProductItemVo.getApplicationNum(),"采购量不能小于到货量!");
                }

            }
        }
    }

    /**
     * 检查变更后的金额不得小于已付款的金额
     * @param model
     */
    public void checkFundsPayOrder(PurchaseChangeOrderVo model){
        final List<FundsPayOrder> fundsPayOrderList = fundsPayOrderService.list(Wrappers.lambdaQuery(FundsPayOrder.class)
                .eq(FundsPayOrder::getAssociatedOrder, model.getOrderSn())
                .eq(FundsPayOrder::getCostType, "FY01"));
        if(CollectionUtil.isNotEmpty(fundsPayOrderList)){
            final BigDecimal paidAmount = fundsPayOrderList.stream().map(pay -> pay.getPaidAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            final BigDecimal totalPrice = model.getProductItem().stream().map(item -> item.getUnitPrice().multiply(new BigDecimal(item.getApplicationNum()))).reduce(BigDecimal.ZERO, BigDecimal::add);
            Assert.isTrue(paidAmount.compareTo(totalPrice) < 0,"变更后的金额不得小于已付款的金额");
        }
    }
}
